package com.tsfyun.common.base.support;

import cn.hutool.core.util.ArrayUtil;
import com.google.common.collect.ImmutableMap;
import com.tsfyun.common.base.enums.domain.DomainOprationEnum;
import com.tsfyun.common.base.enums.domain.*;
import com.tsfyun.common.base.exception.ServiceException;
import com.tsfyun.common.base.util.EntityUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.NonNull;

import java.util.Arrays;
import java.util.Map;
import java.util.Objects;


/**
 * @Description:
 * @since Created in 2020/4/2 16:48
 */
@Slf4j
public class DomainStatus {

    /**
     * 操作定义
     */
    private static Map<String, OperationInfo> operationMap = ImmutableMap.<String, OperationInfo>builder()
            //################协议报价单操作##########################
            //修改
            .put(DomainOprationEnum.AGREEMENT_EDIT.getCode(),
                    new OperationInfo(new String[]{AgreementStatusEnum.SAVED.getCode(),AgreementStatusEnum.WAIT_EDIT.getCode()}))
            //审核
            .put(DomainOprationEnum.AGREEMENT_EXAMINE.getCode(),
                    new OperationInfo(new String[]{AgreementStatusEnum.WAIT_EXAMINE.getCode()}))
            //签署
            .put(DomainOprationEnum.AGREEMENT_SIGN.getCode(),
                    new OperationInfo(new String[]{AgreementStatusEnum.WAIT_CONFIRM.getCode()}))
            //原件签回
            .put(DomainOprationEnum.AGREEMENT_RETURN.getCode(),
                    new OperationInfo(new String[]{AgreementStatusEnum.AUDITED.getCode(),AgreementStatusEnum.INVALID.getCode()}))
            //作废
            .put(DomainOprationEnum.AGREEMENT_INVALID.getCode(),
                    new OperationInfo(EntityUtil.getInstance().getPermitCodes(AgreementStatusEnum.class,AgreementStatusEnum.INVALID.getCode())))
            //删除
            .put(DomainOprationEnum.AGREEMENT_DELETE.getCode(),
                    new OperationInfo(new String[]{AgreementStatusEnum.INVALID.getCode()}))


            //################物料管理操作##########################
            //进口归类
            .put(DomainOprationEnum.MATERIEL_CLASSIFY.getCode(),new OperationInfo(new String[]{MaterielStatusEnum.WAIT_CLASSIFY.getCode(),MaterielStatusEnum.CLASSED.getCode()}))
            //出口归类
            .put(DomainOprationEnum.MATERIEL_CLASSIFY_EXP.getCode(),new OperationInfo(new String[]{MaterielStatusEnum.WAIT_CLASSIFY.getCode(),MaterielStatusEnum.CLASSED.getCode()}))

            //################订单管理操作##########################
            //修改订单
            .put(DomainOprationEnum.ORDER_EDIT.getCode(),new OperationInfo(new String[]{ImpOrderStatusEnum.TEMP_SAVED.getCode(),ImpOrderStatusEnum.WAIT_EDIT.getCode()}))
            //修改国内配送
            .put(DomainOprationEnum.ORDER_EDIT_DISTRIBUTION.getCode(),new OperationInfo(new String[]{
                    ImpOrderStatusEnum.TEMP_SAVED.getCode(),
                    ImpOrderStatusEnum.WAIT_EDIT.getCode(),
                    ImpOrderStatusEnum.WAIT_PRICE.getCode(),
                    ImpOrderStatusEnum.WAIT_EXAMINE.getCode(),
                    ImpOrderStatusEnum.WAIT_INSPECTION.getCode(),
                    ImpOrderStatusEnum.WAIT_CONFIRM_IMP.getCode(),
                    ImpOrderStatusEnum.WAIT_FK_EXAMINE.getCode(),
                    ImpOrderStatusEnum.WAIT_DECLARE.getCode()
            }))
            //订单删除
            .put(DomainOprationEnum.ORDER_REMOVE.getCode(),new OperationInfo(new String[]{ImpOrderStatusEnum.TEMP_SAVED.getCode(),ImpOrderStatusEnum.WAIT_EDIT.getCode()}))
            //订单审价
            .put(DomainOprationEnum.ORDER_PRICING.getCode(),new OperationInfo(new String[]{ImpOrderStatusEnum.WAIT_PRICE.getCode()}))
            //订单审核
            .put(DomainOprationEnum.ORDER_EXAMINE.getCode(),new OperationInfo(new String[]{ImpOrderStatusEnum.WAIT_EXAMINE.getCode()}))
            //订单验货确认
            .put(DomainOprationEnum.ORDER_INSPECTION.getCode(),new OperationInfo(new String[]{ImpOrderStatusEnum.WAIT_INSPECTION.getCode()}))
            // 订单拆单
            .put(DomainOprationEnum.ORDER_SPLIT.getCode(),new OperationInfo(new String[]{ImpOrderStatusEnum.WAIT_INSPECTION.getCode()}))
            //订单进口确认
            .put(DomainOprationEnum.ORDER_CONFIRMIMP.getCode(),new OperationInfo(new String[]{ImpOrderStatusEnum.WAIT_CONFIRM_IMP.getCode()}))
            //订单生成报关单
            .put(DomainOprationEnum.ORDER_CREATE_DECL.getCode(),new OperationInfo(new String[]{ImpOrderStatusEnum.WAIT_CREATE_DECLARE.getCode()}))
            //订单完成风控审核
            .put(DomainOprationEnum.ORDER_COMPLETE_RISK.getCode(),new OperationInfo(new String[]{ImpOrderStatusEnum.WAIT_FK_EXAMINE.getCode()}))
            //订单报关完成
            .put(DomainOprationEnum.ORDER_COMPLETE_DEC.getCode(),new OperationInfo(new String[]{ImpOrderStatusEnum.WAIT_DECLARE.getCode()}))
            //根据订单生产销售合同
            .put(DomainOprationEnum.ORDER_BY_SC.getCode(),new OperationInfo(new String[]{ImpOrderStatusEnum.WAIT_DECLARE.getCode(),ImpOrderStatusEnum.WAIT_CLEARANCE.getCode(),ImpOrderStatusEnum.CLEARED.getCode()}))
            //根据订单做发票申请
            .put(DomainOprationEnum.ORDER_BY_INV.getCode(),new OperationInfo(new String[]{ImpOrderStatusEnum.WAIT_DECLARE.getCode(),ImpOrderStatusEnum.WAIT_CLEARANCE.getCode(),ImpOrderStatusEnum.CLEARED.getCode()}))

            //费用调整
            .put(DomainOprationEnum.ORDER_ADJUST_COST.getCode(),new OperationInfo(
                    EntityUtil.getInstance().getPermitCodes(ImpOrderStatusEnum.class,ImpOrderStatusEnum.TEMP_SAVED.getCode(),ImpOrderStatusEnum.WAIT_PRICE.getCode(),ImpOrderStatusEnum.WAIT_EXAMINE.getCode())
            ))

            //################订单审价操作##########################
            .put(DomainOprationEnum.ORDER_PRICE_EXAMINE.getCode(),new OperationInfo(new String[]{ImpOrderPriceStatusEnum.WAIT_EXAMINE.getCode()}))
            .put(DomainOprationEnum.EXP_ORDER_PRICE_EXAMINE.getCode(),new OperationInfo(new String[]{ExpOrderPriceStatusEnum.WAIT_EXAMINE.getCode()}))

            //#################收款单操作##########################
            //收款确认
            .put(DomainOprationEnum.RECEIPT_CONFIRM.getCode(),new OperationInfo(new String[]{ReceiptAccountStatusEnum.WAIT_CONFIRM.getCode()}))
            //收款作废
            .put(DomainOprationEnum.RECEIPT_CANCLE.getCode(),new OperationInfo(new String[]{ReceiptAccountStatusEnum.WAIT_CONFIRM.getCode(),ReceiptAccountStatusEnum.CONFIRMED.getCode()}))
            //收款删除
            .put(DomainOprationEnum.RECEIPT_REMOVE.getCode(),new OperationInfo(new String[]{ReceiptAccountStatusEnum.INVALID.getCode()}))

            //#################进口付款单操作##########################
            //付款单商务审核
            .put(DomainOprationEnum.PAYMENT_ACCOUNT_AUDIT.getCode(),new OperationInfo(new String[]{PaymentAccountStatusEnum.WAIT_SW_EXAMINE.getCode()}))
            //汇率调整
            .put(DomainOprationEnum.PAYMENT_RATE_ADJUST.getCode(),new OperationInfo(new String[]{PaymentAccountStatusEnum.WAIT_SW_EXAMINE.getCode()}))
            //手续费调整
            .put(DomainOprationEnum.PAYMENT_RATE_BANK_FEE.getCode(),new OperationInfo(new String[]{PaymentAccountStatusEnum.WAIT_SW_EXAMINE.getCode()}))
            //付款单修改
            .put(DomainOprationEnum.PAYMENT_ACCOUNT_EDIT.getCode(),new OperationInfo(new String[]{PaymentAccountStatusEnum.WAITT_EDIT.getCode()}))
            //付款单作废
            .put(DomainOprationEnum.PAYMENT_ACCOUNT_INVALID.getCode(),new OperationInfo(EntityUtil.getInstance().getPermitCodes(PaymentAccountStatusEnum.class,PaymentAccountStatusEnum.TO_VOID.getCode())))
            //付款单删除
            .put(DomainOprationEnum.PAYMENT_ACCOUNT_REMOVE.getCode(),new OperationInfo(new String[]{PaymentAccountStatusEnum.TO_VOID.getCode()}))
            //等待风控审批
            .put(DomainOprationEnum.PAYMENT_WAIT_RISK_AUDIT.getCode(),new OperationInfo(new String[]{PaymentAccountStatusEnum.WAIT_FK_EXAMINE.getCode()}))
            //确定付款行
            .put(DomainOprationEnum.PAYMENT_WAIT_CONFIRM_BANK.getCode(),new OperationInfo(new String[]{PaymentAccountStatusEnum.CONFIRM_BANK.getCode()}))
            //确定付汇完成
            .put(DomainOprationEnum.PAYMENT_CONFIRM_PAY.getCode(),new OperationInfo(new String[]{PaymentAccountStatusEnum.WAIT_PAY.getCode()}))


            //#################跨境运输操作(进口)##########################
            //删除跨境运输单
            .put(DomainOprationEnum.CROSS_BORDER_WAYBILL_DELETE.getCode(),new OperationInfo(new String[]{CrossBorderWaybillStatusEnum.WAIT_CONFIRM.getCode()}))
            //修改跨境运输单
            .put(DomainOprationEnum.CROSS_BORDER_WAYBILL_EDIT.getCode(),new OperationInfo(new String[]{CrossBorderWaybillStatusEnum.WAIT_CONFIRM.getCode()}))
            //确认跨境运输单
            .put(DomainOprationEnum.CROSS_BORDER_WAYBILL_CONFIRM.getCode(),new OperationInfo(new String[]{CrossBorderWaybillStatusEnum.WAIT_CONFIRM.getCode()}))
            //绑单
            .put(DomainOprationEnum.CROSS_BORDER_WAYBILL_BIND.getCode(),new OperationInfo(new String[]{CrossBorderWaybillStatusEnum.WAIT_BIND.getCode()}))
            //退回
            .put(DomainOprationEnum.CROSS_BORDER_WAYBILL_BACK.getCode(),new OperationInfo(new String[]{CrossBorderWaybillStatusEnum.WAIT_BIND.getCode()}))
            //复核
            .put(DomainOprationEnum.CROSS_BORDER_WAYBILL_REVIRE.getCode(),new OperationInfo(new String[]{CrossBorderWaybillStatusEnum.WAIT_REVIEW.getCode()}))
            //发车
            .put(DomainOprationEnum.CROSS_BORDER_WAYBILL_DEPART.getCode(),new OperationInfo(new String[]{CrossBorderWaybillStatusEnum.WAIT_DEPART.getCode()}))
            //签收
            .put(DomainOprationEnum.CROSS_BORDER_WAYBILL_SIGN.getCode(),new OperationInfo(new String[]{CrossBorderWaybillStatusEnum.WAIT_SIGN.getCode()}))

            //#################跨境运输操作(出口)##########################
            //删除跨境运输单
            .put(DomainOprationEnum.EXP_CROSS_BORDER_WAYBILL_DELETE.getCode(),new OperationInfo(new String[]{CrossBorderWaybillStatusEnum.WAIT_CONFIRM.getCode()}))
            //修改跨境运输单
            .put(DomainOprationEnum.EXP_CROSS_BORDER_WAYBILL_EDIT.getCode(),new OperationInfo(new String[]{CrossBorderWaybillStatusEnum.WAIT_CONFIRM.getCode()}))
            //确认跨境运输单
            .put(DomainOprationEnum.EXP_CROSS_BORDER_WAYBILL_CONFIRM.getCode(),new OperationInfo(new String[]{CrossBorderWaybillStatusEnum.WAIT_CONFIRM.getCode()}))
            //绑单
            .put(DomainOprationEnum.EXP_CROSS_BORDER_WAYBILL_BIND.getCode(),new OperationInfo(new String[]{CrossBorderWaybillStatusEnum.WAIT_BIND.getCode()}))
            //退回
            .put(DomainOprationEnum.EXP_CROSS_BORDER_WAYBILL_BACK.getCode(),new OperationInfo(new String[]{CrossBorderWaybillStatusEnum.WAIT_BIND.getCode()}))
            //复核
            .put(DomainOprationEnum.EXP_CROSS_BORDER_WAYBILL_REVIRE.getCode(),new OperationInfo(new String[]{CrossBorderWaybillStatusEnum.WAIT_REVIEW.getCode()}))
            //发车
            .put(DomainOprationEnum.EXP_CROSS_BORDER_WAYBILL_DEPART.getCode(),new OperationInfo(new String[]{CrossBorderWaybillStatusEnum.WAIT_DEPART.getCode()}))
            //签收
            .put(DomainOprationEnum.EXP_CROSS_BORDER_WAYBILL_SIGN.getCode(),new OperationInfo(new String[]{CrossBorderWaybillStatusEnum.WAIT_SIGN.getCode()}))

            //##################国内送货操作#########################
            //确认国内送货
            .put(DomainOprationEnum.DELIVERY_WAYBILL_CONFIRM.getCode(),new OperationInfo(new String[]{DeliveryWaybillStatusEnum.WAIT_CONFIRM.getCode()}))
            //国内送货发车确认
            .put(DomainOprationEnum.DELIVERY_WAYBILL_DEPART.getCode(),new OperationInfo(new String[]{DeliveryWaybillStatusEnum.WAIT_DEPART.getCode()}))
            //国内送货签收确认
            .put(DomainOprationEnum.DELIVERY_WAYBILL_SIGN.getCode(),new OperationInfo(new String[]{DeliveryWaybillStatusEnum.WAIT_SIGN.getCode()}))

            //##################报关单操作(进口)###########################
            //确认报关单
            .put(DomainOprationEnum.DECLARATION_CONFIRM.getCode(),new OperationInfo(new String[]{DeclarationStatusEnum.WAIT_CONFIRM.getCode()}))
            //确认申报报关单
            .put(DomainOprationEnum.DECLARATION_DECLARE.getCode(),new OperationInfo(new String[]{DeclarationStatusEnum.WAIT_DECLARE.getCode()}))
            //发送单一窗口
            .put(DomainOprationEnum.DECLARATION_SEND_SINGLE.getCode(),new OperationInfo(new String[]{DeclarationStatusEnum.IN_DECLARE.getCode()}))
            //舱单发送/删除
            .put(DomainOprationEnum.DECLARATION_SEND_MANIFEST.getCode(),new OperationInfo(new String[]{DeclarationStatusEnum.IN_DECLARE.getCode(),DeclarationStatusEnum.WAIT_DECLARE.getCode()}))
            //发送至申报
            .put(DomainOprationEnum.DECLARATION_SEND_SCMBOT.getCode(),new OperationInfo(new String[]{DeclarationStatusEnum.IN_DECLARE.getCode()}))
            //申报完成
            .put(DomainOprationEnum.DECLARATION_COMPLETED.getCode(),new OperationInfo(new String[]{DeclarationStatusEnum.IN_DECLARE.getCode()}))

            //##################报关单操作(出口)###########################
            //确认报关单
            .put(DomainOprationEnum.EXP_DECLARATION_CONFIRM.getCode(),new OperationInfo(new String[]{DeclarationStatusEnum.WAIT_CONFIRM.getCode()}))
            //确认申报报关单
            .put(DomainOprationEnum.EXP_DECLARATION_DECLARE.getCode(),new OperationInfo(new String[]{DeclarationStatusEnum.WAIT_DECLARE.getCode()}))
            //发送单一窗口
            .put(DomainOprationEnum.EXP_DECLARATION_SEND_SINGLE.getCode(),new OperationInfo(new String[]{DeclarationStatusEnum.IN_DECLARE.getCode()}))
            //舱单发送/删除
            .put(DomainOprationEnum.EXP_DECLARATION_SEND_MANIFEST.getCode(),new OperationInfo(new String[]{DeclarationStatusEnum.IN_DECLARE.getCode(),DeclarationStatusEnum.WAIT_DECLARE.getCode()}))
            //发送至申报
            .put(DomainOprationEnum.EXP_DECLARATION_SEND_SCMBOT.getCode(),new OperationInfo(new String[]{DeclarationStatusEnum.IN_DECLARE.getCode()}))
            //申报完成
            .put(DomainOprationEnum.EXP_DECLARATION_COMPLETED.getCode(),new OperationInfo(new String[]{DeclarationStatusEnum.IN_DECLARE.getCode()}))

            //##################代理报关单操作###########################
            .put(DomainOprationEnum.TRUSTORDER_REMOVE.getCode(),new OperationInfo(new String[]{"wait_receive"}))
            .put(DomainOprationEnum.TRUSTORDER_RECEIVING.getCode(),new OperationInfo(new String[]{"wait_receive"}))

            //##################代理报关报价单操作###########################
            //修改
            .put(DomainOprationEnum.DECL_QUOTE_EDIT.getCode(),new OperationInfo(new String[]{DeclQuoteStatusEnum.SAVED.getCode(),DeclQuoteStatusEnum.WAIT_EDIT.getCode()}))
            //审核
            .put(DomainOprationEnum.DECL_QUOTE_EXAMINE.getCode(),new OperationInfo(new String[]{DeclQuoteStatusEnum.WAIT_EXAMINE.getCode()}))
            //作废
            .put(DomainOprationEnum.DECL_QUOTE_INVALID.getCode(),new OperationInfo(EntityUtil.getInstance().getPermitCodes(DeclQuoteStatusEnum.class,DeclQuoteStatusEnum.INVALID.getCode())))
            //删除
            .put(DomainOprationEnum.DECL_QUOTE_DELETE.getCode(),new OperationInfo(new String[]{DeclQuoteStatusEnum.INVALID.getCode()}))


            //###############风控审批操作###############################
            //风控审批
            .put(DomainOprationEnum.RISK_APPROVAL_AUDIT.getCode(),new OperationInfo(new String[]{RiskApprovalStatusEnum.WAIT_EXAMINE.getCode()}))




            //##################发票操作#################################
            //发票删除
            .put(DomainOprationEnum.INVOICE_DELETE.getCode(),new OperationInfo(EntityUtil.getInstance().getPermitCodes(InvoiceStatusEnum.class)))
            //财务确定编码
            .put(DomainOprationEnum.INVOICE_CONFIRM_TAX.getCode(),new OperationInfo(new String[]{InvoiceStatusEnum.WAIT_FINANCE_TAX.getCode()}))
            //客户确定编码
            .put(DomainOprationEnum.INVOICE_CONFIRM_CUSTOMER.getCode(),new OperationInfo(new String[]{InvoiceStatusEnum.WAIT_CUSTOMER_TAX.getCode()}))
            //商务开票确认
            .put(DomainOprationEnum.INVOICE_CONFIRM_SALE.getCode(),new OperationInfo(new String[]{InvoiceStatusEnum.WAIT_CONFIRM.getCode()}))
            //发票确认开票完成
            .put(DomainOprationEnum.INVOICE_CW_COMPLETE.getCode(),new OperationInfo(new String[]{InvoiceStatusEnum.WAIT_FINANCE_CONFIRM.getCode()}))

            //##################客户操作####################################
            //审核
            .put(DomainOprationEnum.CUSTOMER_APPROVE.getCode(),
                    new OperationInfo(new String[]{CustomerStatusEnum.TYPE_1.getCode()}))


            //###################退款操作####################################
            //审核
            .put(DomainOprationEnum.REFUND_AUDIT.getCode(),new OperationInfo(new String[]{RefundAccountStatusEnum.WAIT_EXAMINE.getCode()}))
            //确定付款行
            .put(DomainOprationEnum.REFUND_CONFIRM_BANK.getCode(),new OperationInfo(new String[]{RefundAccountStatusEnum.CONFIRM_BANK.getCode()}))
            //上传水单
            .put(DomainOprationEnum.REFUND_BANK_RECEIPT.getCode(),new OperationInfo(new String[]{RefundAccountStatusEnum.WAIT_PAY.getCode()}))
            //删除
            .put(DomainOprationEnum.REFUND_REMOVE.getCode(),new OperationInfo(new String[]{RefundAccountStatusEnum.NOT_APPROVE.getCode()}))

            //################出口订单########################
            //删除
            .put(DomainOprationEnum.EXP_ORDER_REMOVE.getCode(),new OperationInfo(new String[]{ExpOrderStatusEnum.TEMP_SAVED.getCode(),ExpOrderStatusEnum.WAIT_EDIT.getCode()}))
            //订单审价
            .put(DomainOprationEnum.EXP_ORDER_PRICING.getCode(),new OperationInfo(new String[]{ExpOrderStatusEnum.WAIT_PRICE.getCode()}))
            //修改订单
            .put(DomainOprationEnum.EXP_ORDER_EDIT.getCode(),new OperationInfo(new String[]{ExpOrderStatusEnum.TEMP_SAVED.getCode(),ExpOrderStatusEnum.WAIT_EDIT.getCode()}))
            //订单审核
            .put(DomainOprationEnum.EXP_ORDER_EXAMINE.getCode(),new OperationInfo(new String[]{ExpOrderStatusEnum.WAIT_EXAMINE.getCode()}))
            //订单验货确认
            .put(DomainOprationEnum.EXP_ORDER_INSPECTION.getCode(),new OperationInfo(new String[]{ExpOrderStatusEnum.WAIT_INSPECTION.getCode()}))
            //订单出口确认
            .put(DomainOprationEnum.EXP_ORDER_CONFIRMIMP.getCode(),new OperationInfo(new String[]{ExpOrderStatusEnum.WAIT_CONFIRM_EXP.getCode()}))
            //订单报关完成
            .put(DomainOprationEnum.EXP_ORDER_COMPLETE_DEC.getCode(),new OperationInfo(new String[]{ExpOrderStatusEnum.WAIT_DECLARE.getCode()}))
            //费用调整
            .put(DomainOprationEnum.EXP_ORDER_ADJUST_COST.getCode(),new OperationInfo(
                    EntityUtil.getInstance().getPermitCodes(ExpOrderStatusEnum.class,ExpOrderStatusEnum.TEMP_SAVED.getCode(),ExpOrderStatusEnum.WAIT_PRICE.getCode(),ExpOrderStatusEnum.WAIT_EXAMINE.getCode())
            ))
            //做采购合同
            .put(DomainOprationEnum.CREATE_PURCHASE_CONTRACT.getCode(),new OperationInfo(new String[]{ExpOrderStatusEnum.WAIT_DECLARE.getCode(),ExpOrderStatusEnum.WAIT_CLEARANCE.getCode(),ExpOrderStatusEnum.CLEARED.getCode(),
                    ExpOrderStatusEnum.SIGNED.getCode()}))

            //################采购合同操作##########################
            .put(DomainOprationEnum.PURCHASE_CONTRACT_CONFIRM.getCode(),new OperationInfo(new String[]{PurchaseContractStatusEnum.WAIT_CONFIRM.getCode()}))
            .put(DomainOprationEnum.PURCHASE_CONTRACT_INVOICE.getCode(),new OperationInfo(new String[]{PurchaseContractStatusEnum.WAIT_INVOICE.getCode()}))
            .put(DomainOprationEnum.PURCHASE_CONTRACT_REMOVE.getCode(),new OperationInfo(new String[]{PurchaseContractStatusEnum.WAIT_CONFIRM.getCode(),PurchaseContractStatusEnum.WAIT_INVOICE.getCode()}))
            .put(DomainOprationEnum.PURCHASE_CONTRACT_DRAWNACK.getCode(),new OperationInfo(new String[]{PurchaseContractStatusEnum.COMPLETE.getCode()}))
            .put(DomainOprationEnum.PURCHASE_TAX_BUREAU.getCode(),new OperationInfo(new String[]{PurchaseContractStatusEnum.COMPLETE.getCode()}))
            .put(DomainOprationEnum.PURCHASE_CONTRACT_SENDMAIL.getCode(),new OperationInfo(new String[]{PurchaseContractStatusEnum.COMPLETE.getCode()}))

            //################协议报价单操作##########################
            //修改
            .put(DomainOprationEnum.EXP_AGREEMENT_EDIT.getCode(),
                    new OperationInfo(new String[]{ExpAgreementStatusEnum.SAVED.getCode(),ExpAgreementStatusEnum.WAIT_EDIT.getCode()}))
            //审核
            .put(DomainOprationEnum.EXP_AGREEMENT_EXAMINE.getCode(),
                    new OperationInfo(new String[]{ExpAgreementStatusEnum.WAIT_EXAMINE.getCode()}))
            //原件签回
            .put(DomainOprationEnum.EXP_AGREEMENT_RETURN.getCode(),
                    new OperationInfo(new String[]{ExpAgreementStatusEnum.AUDITED.getCode(),ExpAgreementStatusEnum.INVALID.getCode()}))
            //作废
            .put(DomainOprationEnum.EXP_AGREEMENT_INVALID.getCode(),
                    new OperationInfo(EntityUtil.getInstance().getPermitCodes(ExpAgreementStatusEnum.class,ExpAgreementStatusEnum.INVALID.getCode())))
            //删除
            .put(DomainOprationEnum.EXP_AGREEMENT_DELETE.getCode(),
                    new OperationInfo(new String[]{ExpAgreementStatusEnum.INVALID.getCode()}))

            //################境外收款操作################################
            .put(DomainOprationEnum.OVERSEAS_RECEIVING_ACCOUNT_EDIT.getCode(),new OperationInfo(new String[]{OverseasReceivingAccountStatusEnum.WAIT_CONFIRM.getCode()}))
            .put(DomainOprationEnum.OVERSEAS_RECEIVING_ACCOUNT_CONFIRM.getCode(),new OperationInfo(new String[]{OverseasReceivingAccountStatusEnum.WAIT_CONFIRM.getCode()}))
            .put(DomainOprationEnum.OVERSEAS_RECEIVING_ACCOUNT_CLAIM.getCode(),new OperationInfo(new String[]{OverseasReceivingAccountStatusEnum.WAIT_CLAIM.getCode()}))
            .put(DomainOprationEnum.OVERSEAS_RECEIVING_ACCOUNT_CANCEL.getCode(), new OperationInfo(EntityUtil.getInstance().getPermitCodes(OverseasReceivingAccountStatusEnum.class,ExpAgreementStatusEnum.INVALID.getCode())))
            .put(DomainOprationEnum.OVERSEAS_RECEIVING_ACCOUNT_REMOVE.getCode(),new OperationInfo(new String[]{OverseasReceivingAccountStatusEnum.INVALID.getCode()}))
            .put(DomainOprationEnum.OVERSEAS_RECEIVING_ACCOUNT_SETTLEMENT.getCode(),new OperationInfo(new String[]{OverseasReceivingAccountStatusEnum.COMPLETE.getCode()}))
            .put(DomainOprationEnum.OVERSEAS_RECEIVING_ACCOUNT_PAYMENT.getCode(),new OperationInfo(new String[]{OverseasReceivingAccountStatusEnum.COMPLETE.getCode()}))

            //################出口付款操作################################
            .put(DomainOprationEnum.EXP_PAYMENT_ACCOUNT_CONFIRM.getCode(),new OperationInfo(new String[]{ExpPaymentAccountStatusEnum.WAIT_CONFIRM.getCode()}))
            .put(DomainOprationEnum.EXP_PAYMENT_ACCOUNT_BANK.getCode(),new OperationInfo(new String[]{ExpPaymentAccountStatusEnum.CONFIRM_BANK.getCode()}))
            .put(DomainOprationEnum.EXP_PAYMENT_ACCOUNT_COMPLETED.getCode(),new OperationInfo(new String[]{ExpPaymentAccountStatusEnum.WAIT_PAY.getCode()}))
            .put(DomainOprationEnum.EXP_PAYMENT_ACCOUNT_REMOVE.getCode(),new OperationInfo(new String[]{ExpPaymentAccountStatusEnum.WAIT_CONFIRM.getCode()}))

            //################出口退税操作################################
            .put(DomainOprationEnum.DRAWBACK_CONFIRM.getCode(),new OperationInfo(new String[]{DrawbackStatusEnum.WAIT_CONFIRM.getCode()}))
            .put(DomainOprationEnum.DRAWBACK_BANK.getCode(),new OperationInfo(new String[]{DrawbackStatusEnum.CONFIRM_BANK.getCode()}))
            .put(DomainOprationEnum.DRAWBACK_COMPLETED.getCode(),new OperationInfo(new String[]{DrawbackStatusEnum.WAIT_PAY.getCode()}))
            .put(DomainOprationEnum.DRAWBACK_REMOVE.getCode(),new OperationInfo(new String[]{DrawbackStatusEnum.WAIT_CONFIRM.getCode()}))


            //###############境外派送操作###################################
            .put(DomainOprationEnum.EXP_OVERSEAS_DELIVERY_NOTE_EDIT.getCode(),new OperationInfo(new String[]{OverseasDeliveryNoteStatusEnum.WAIT_CONFIRM.getCode()}))
            .put(DomainOprationEnum.EXP_OVERSEAS_DELIVERY_NOTE_CONFIRM.getCode(),new OperationInfo(new String[]{OverseasDeliveryNoteStatusEnum.WAIT_CONFIRM.getCode()}))
            .put(DomainOprationEnum.EXP_OVERSEAS_DELIVERY_NOTE_DISTRIBUTION.getCode(),new OperationInfo(new String[]{OverseasDeliveryNoteStatusEnum.WAIT_DELIVERY.getCode()}))
            .put(DomainOprationEnum.EXP_OVERSEAS_DELIVERY_NOTE_SIGN.getCode(),new OperationInfo(new String[]{OverseasDeliveryNoteStatusEnum.DELIVERING.getCode()}))
            .put(DomainOprationEnum.EXP_OVERSEAS_DELIVERY_NOTE_DELETE.getCode(),new OperationInfo(new String[]{OverseasDeliveryNoteStatusEnum.WAIT_CONFIRM.getCode()}))
            .build();

    /**
     * 内部类单例模式
     */
    private static class DomainStatusCheckInstance{
        private static final DomainStatus instance = new DomainStatus();
    }

    private DomainStatus(){}

    public static DomainStatus getInstance(){
        return DomainStatusCheckInstance.instance;
    }

    public Map<String, OperationInfo> getOperationMap() {
        return operationMap;
    }

    /**
     * 校验单据当前状态是否支持操作
     * @param operationEnum 操作码，枚举DomainOprationEnum
     * @param statusCode 当前单据状态编码
     */
    public void check(DomainOprationEnum operationEnum,@NonNull String statusCode) {
        if(Objects.isNull(operationEnum)){return;}
        //获取操作定义map
        if(Objects.nonNull(operationMap) && Objects.nonNull(operationMap.get(operationEnum.getCode()))) {
            OperationInfo operationInfo = operationMap.get(operationEnum.getCode());
            if(Objects.isNull(operationInfo)) {
                log.warn("未配置操作码【{}】状态映射数据",operationEnum.getCode());
            }
            if(ArrayUtil.isNotEmpty(operationInfo.getStatus()) && !Arrays.asList(operationInfo.getStatus()).contains(statusCode)) {
                throw new ServiceException("当前状态不允许此操作");
            }
        } else {
            log.warn("未定义单据操作状态，不校验");
        }
    }

}
